package com.xuecheng.ucenter.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.xuecheng.ucenter.mapper.XcUserMapper;
import com.xuecheng.ucenter.mapper.XcUserRoleMapper;
import com.xuecheng.ucenter.model.dto.AuthParamsDto;
import com.xuecheng.ucenter.model.dto.XcUserExt;
import com.xuecheng.ucenter.model.po.XcUser;
import com.xuecheng.ucenter.model.po.XcUserRole;
import com.xuecheng.ucenter.service.AuthService;
import com.xuecheng.ucenter.service.WxAuthService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

/**
 * @author: Hes
 * @description 微信认证实现
 * @date: 2023/6/26 16:50
 */
@Slf4j
@Service("wx_authservice")
public class WxAuthServiceImpl implements AuthService, WxAuthService {
    @Value("${weixin.appid}")
    private String appid;
    @Value("${weixin.secret}")
    private String secret;

    @Autowired
    RestTemplate restTemplate;
    @Autowired
    XcUserMapper xcUserMapper;

    @Autowired
    XcUserRoleMapper xcUserRoleMapper;

    @Autowired
    WxAuthServiceImpl currentProxy;

    /**
     * 获取到当前登录的用户
     *
     * @param authParamsDto 认证参数
     * @return
     */
    @Override
    public XcUserExt execute(AuthParamsDto authParamsDto) {
        String username = authParamsDto.getUsername();
        XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>().eq(XcUser::getUsername, username));
        if (xcUser == null) {
            throw new RuntimeException("用户不存在");
        }
        XcUserExt xcUserExt = new XcUserExt();
        BeanUtils.copyProperties(xcUser, xcUserExt);
        return xcUserExt;
    }

    /**
     * 微信扫码后，根据code获取用户信息
     *
     * @param code
     * @return
     */
    @Override
    public XcUser weAuth(String code) {
        if (StringUtils.isEmpty(code)) {
            log.debug("微信回调的code：{}", code);
            throw new RuntimeException("微信回调的code为空");
        }
        //获取令牌
        Map<String, String> result = getAccess_token(code);
        if (result == null) {
            return null;
        }
        String access_token = result.get("access_token");
        String openid = result.get("openid");
        //获取用户信息
        Map<String, String> userinfo = getUserinfo(access_token, openid);
        if (userinfo == null) {
            return null;
        }
        //保存用户信息
        XcUser xcUser = currentProxy.addWxUser(userinfo);
        return xcUser;
    }

    @Transactional
    public XcUser addWxUser(Map<String, String> map) {
        String unionid = map.get("unionid").toString();
        String nickname = map.get("nickname").toString();
        String headimgurl = map.get("headimgurl");
        XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>().eq(XcUser::getWxUnionid, unionid));
        if (xcUser != null) {
            return xcUser;
        }
        String userId = UUID.randomUUID().toString();
        xcUser = new XcUser();
        xcUser.setId(userId);
        xcUser.setPassword(unionid);
        xcUser.setUsername(nickname);
        xcUser.setWxUnionid(unionid);
        xcUser.setName(nickname);
        xcUser.setUserpic(headimgurl);
        xcUser.setCompanyId("1232141425");
        xcUser.setUtype("101002");
        xcUser.setSex("0");
        xcUser.setStatus("1");
        xcUser.setCreateTime(LocalDateTime.now());
        int insert = xcUserMapper.insert(xcUser);
        if (insert < 0) {
            throw new RuntimeException("添加用户信息失败");
        }
        XcUserRole xcUserRole = new XcUserRole();
        xcUserRole.setUserId(userId);
        xcUserRole.setRoleId("17");
        xcUserRole.setId(UUID.randomUUID().toString());
        xcUserRole.setCreateTime(LocalDateTime.now());
        xcUserRoleMapper.insert(xcUserRole);
        return xcUser;
    }

    /**
     * 获取微信令牌
     * * 申请访问令牌,响应示例
     * {
     * "access_token":"ACCESS_TOKEN",
     * "expires_in":7200,
     * "refresh_token":"REFRESH_TOKEN",
     * "openid":"OPENID",
     * "scope":"SCOPE",
     * "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
     * }
     *
     * @param code
     * @return
     */
    private Map<String, String> getAccess_token(String code) {
        //使用?占位符，在把数据填充
        String urlTemp = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
        String url = String.format(urlTemp, appid, secret, code);
        log.debug("调用微信接口url: {}", url);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
        log.debug("调用微信接口申请access_token: 返回值:{}", response);
        String body = response.getBody();
        Map<String, String> map = JSON.parseObject(body, Map.class);
        return map;
    }

    /**
     * {
     * "openid":"OPENID",
     * "nickname":"NICKNAME",
     * "sex":1,
     * "province":"PROVINCE",
     * "city":"CITY",
     * "country":"COUNTRY",
     * "headimgurl": "https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
     * "privilege":[
     * "PRIVILEGE1",
     * "PRIVILEGE2"
     * ],
     * "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
     * <p>
     * }
     */
    private Map<String, String> getUserinfo(String access_token, String openid) {
        String urlTemp = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
        String url = String.format(urlTemp, access_token, openid);
        log.debug("调用微信获取用户信息接口,url:{}", url);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
        log.debug("微信获取用户信息接口响应结果,response:{}", response);
        //响应内容进行转码，汉字进行转码
        String body = new String(response.getBody().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

        Map<String, String> map = JSON.parseObject(body, Map.class);
        return map;
    }
}
